home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / symb_lib / symbolic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-23  |  63.6 KB  |  1,566 lines

  1. /******************************************************************************
  2. * Symbolic.c - Generic symbolic computation.                      *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Nov. 92.                          *
  5. ******************************************************************************/
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "symb_loc.h"
  11.  
  12. static CagdCrvStruct *SymbCrvAddSubAux(CagdCrvStruct *Crv1,
  13.                        CagdCrvStruct *Crv2,
  14.                        CagdBType OperationAdd);
  15. static CagdSrfStruct *SymbSrfAddSubAux(CagdSrfStruct *Srf1,
  16.                        CagdSrfStruct *Srf2,
  17.                        CagdBType OperationAdd);
  18.  
  19. /*****************************************************************************
  20. * DESCRIPTION:                                                               M
  21. * Given two curves - add them coordinatewise.                     M
  22. *   The two curves are promoted to same point type before the multiplication M
  23. * can take place. Furthermore, order and continuity are matched as well.     M
  24. *                                                                            *
  25. * PARAMETERS:                                                                M
  26. *   Crv1, Crv2:  Two curve to add up coordinatewise.                         M
  27. *                                                                            *
  28. * RETURN VALUE:                                                              M
  29. *   CagdCrvStruct *:   The summation of Crv1 + Crv2 coordinatewise.          M
  30. *                                                                            *
  31. * KEYWORDS:                                                                  M
  32. *   SymbCrvAdd, addition, symbolic computation                               M
  33. *****************************************************************************/
  34. CagdCrvStruct *SymbCrvAdd(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  35. {
  36.     return SymbCrvAddSubAux(Crv1, Crv2, TRUE);
  37. }
  38.  
  39. /*****************************************************************************
  40. * DESCRIPTION:                                                               M
  41. * Given two curves - subtract them coordinatewise.                 M
  42. *   The two curves are promoted to same point type before the multiplication M
  43. * can take place. Furthermore, order and continuity are matched as well.     M
  44. *                                                                            *
  45. * PARAMETERS:                                                                M
  46. *   Crv1, Crv2:  Two curve to subtract coordinatewise.                       M
  47. *                                                                            *
  48. * RETURN VALUE:                                                              M
  49. *   CagdCrvStruct *:   The difference of Crv1 - Crv2 coordinatewise.         M
  50. *                                                                            *
  51. * KEYWORDS:                                                                  M
  52. *   SymbCrvSub, subtraction, symbolic computation                            M
  53. *****************************************************************************/
  54. CagdCrvStruct *SymbCrvSub(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  55. {
  56.     return SymbCrvAddSubAux(Crv1, Crv2, FALSE);
  57. }
  58.  
  59. /*****************************************************************************
  60. * DESCRIPTION:                                                               M
  61. * Given two curves - multiply them coordinatewise.                 M
  62. *   The two curves are promoted to same point type before the multiplication M
  63. * can take place.                                 M
  64. *                                                                            *
  65. * PARAMETERS:                                                                M
  66. *   Crv1, Crv2:  Two curve to multiply coordinatewise.                       M
  67. *                                                                            *
  68. * RETURN VALUE:                                                              M
  69. *   CagdCrvStruct *:   The product of Crv1 * Crv2 coordinatewise.            M
  70. *                                                                            *
  71. * KEYWORDS:                                                                  M
  72. *   SymbCrvMult, product, symbolic computation                               M
  73. *****************************************************************************/
  74. CagdCrvStruct *SymbCrvMult(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  75. {
  76.     CagdCrvStruct
  77.     *ProdCrv = NULL;
  78.  
  79.     switch (Crv1 -> GType) {
  80.     case CAGD_CBEZIER_TYPE:
  81.         ProdCrv = BzrCrvMult(Crv1, Crv2);
  82.         break;
  83.     case CAGD_CBSPLINE_TYPE:
  84.         ProdCrv = BspCrvMult(Crv1, Crv2);
  85.         break;
  86.     case CAGD_CPOWER_TYPE:
  87.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  88.         break;
  89.     default:
  90.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_CRV);
  91.         break;
  92.     }
  93.  
  94.     return ProdCrv;
  95. }
  96.  
  97. /*****************************************************************************
  98. * DESCRIPTION:                                                               M
  99. * Given a scalar curve, returns a scalar curve representing the reciprocal   M
  100. * values, by making it rational (if was not one) and flipping the numerator  M
  101. * and the denominator.                                        M
  102. *                                                                            *
  103. * PARAMETERS:                                                                M
  104. *   Crv:       A scalar curve to compute a reciprocal value for.             M
  105. *                                                                            *
  106. * RETURN VALUE:                                                              M
  107. *   CagdCrvStruct *:   A rational scalar curve that is equalto the           M
  108. *                      reciprocal value of Crv.                              M
  109. * KEYWORDS:                                                                  M
  110. *   SymbCrvInvert, division, symbolic computation, reciprocal value          M
  111. *****************************************************************************/
  112. CagdCrvStruct *SymbCrvInvert(CagdCrvStruct *Crv)
  113. {
  114.     int i;
  115.     CagdRType *R, **Points;
  116.  
  117.     Crv = CagdCrvCopy(Crv);
  118.     Points = Crv -> Points;
  119.  
  120.     switch (Crv -> PType) {
  121.     case CAGD_PT_E1_TYPE:
  122.         Points[0] = Points[1];
  123.         Points[1] = R = (CagdRType *) IritMalloc(sizeof(CagdRType) *
  124.                                 Crv -> Length);
  125.         for (i = 0; i < Crv -> Length; i++)
  126.         *R++ = 1.0;
  127.         Crv -> PType = CAGD_PT_P1_TYPE;
  128.         break;
  129.     case CAGD_PT_P1_TYPE:
  130.         R = Points[0];
  131.         Points[0] = Points[1];
  132.         Points[1] = R;
  133.         break;
  134.     default:
  135.         SYMB_FATAL_ERROR(SYMB_ERR_UNSUPPORT_PT);
  136.         break;
  137.     }
  138.  
  139.     return Crv;
  140. }
  141.  
  142. /*****************************************************************************
  143. * DESCRIPTION:                                                               M
  144. * Given a curve, scale it by Scale.                         M
  145. *                                                                            *
  146. * PARAMETERS:                                                                M
  147. *   Crv:      A curve to scale by magnitude Scale.                           M
  148. *   Scale:    Scaling factor.                                                M
  149. *                                                                            *
  150. * RETURN VALUE:                                                              M
  151. *   CagdCrvStruct *:   A curves scaled by Scale compared to Crv.             M
  152. *                                                                            *
  153. * KEYWORDS:                                                                  M
  154. *   SymbCrvScalarScale, scaling, symbolic computation                        M
  155. *****************************************************************************/
  156. CagdCrvStruct *SymbCrvScalarScale(CagdCrvStruct *Crv, CagdRType Scale)
  157. {
  158.     int i, j;
  159.     CagdRType *R;
  160.  
  161.     Crv = CagdCrvCopy(Crv);
  162.  
  163.     for (j = 1; j <= CAGD_NUM_OF_PT_COORD(Crv -> PType); j++)
  164.     for (i = 0, R = Crv -> Points[j]; i < Crv -> Length; i++)
  165.         *R++ *= Scale;
  166.  
  167.     return Crv;
  168. }
  169.  
  170. /*****************************************************************************
  171. * DESCRIPTION:                                                               M
  172. * Given two curves - computes their dot product.                 M
  173. *   Returned curve is a scalar curve representing the dot product of the     M
  174. * two given curves.                                 M
  175. *                                                                            *
  176. * PARAMETERS:                                                                M
  177. *   Crv1, Crv2:  Two curve to multiply and compute a dot product for.        M
  178. *                                                                            *
  179. * RETURN VALUE:                                                              M
  180. *   CagdCrvStruct *:   A scalar curve representing the dot product of        M
  181. *                      Crv1 . Crv2.                                          M
  182. *                                                                            *
  183. * KEYWORDS:                                                                  M
  184. *   SymbCrvDotProd, product, dot product, symbolic computation               M
  185. *****************************************************************************/
  186. CagdCrvStruct *SymbCrvDotProd(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  187. {
  188.     CagdCrvStruct *PCrvW, *PCrvX, *PCrvY, *PCrvZ, *TCrv1, *TCrv2, *DotProdCrv,
  189.     *ProdCrv = SymbCrvMult(Crv1, Crv2);
  190.  
  191.     SymbCrvSplitScalar(ProdCrv, &PCrvW, &PCrvX, &PCrvY, &PCrvZ);
  192.     CagdCrvFree(ProdCrv);
  193.  
  194.     if (PCrvY != NULL) {
  195.     TCrv1 = SymbCrvAdd(PCrvX, PCrvY);
  196.     CagdCrvFree(PCrvX);
  197.     CagdCrvFree(PCrvY);
  198.     }
  199.     else
  200.     TCrv1 = PCrvX;
  201.  
  202.     if (PCrvZ != NULL) {
  203.     TCrv2 = SymbCrvAdd(TCrv1, PCrvZ);
  204.     CagdCrvFree(TCrv1);
  205.     CagdCrvFree(PCrvZ);
  206.     TCrv1 = TCrv2;
  207.     }
  208.  
  209.     DotProdCrv = SymbCrvMergeScalar(PCrvW, TCrv1, NULL, NULL);
  210.     CagdCrvFree(PCrvW);
  211.     CagdCrvFree(TCrv1);
  212.  
  213.     return DotProdCrv;
  214. }
  215.  
  216. /*****************************************************************************
  217. * DESCRIPTION:                                                               M
  218. * Given two curves - a vector curve Crv1 and a scalar curve Crv2, multiply   M
  219. * all Crv1's coordinates by the scalar curve Crv2.                 M
  220. *   Returned curve is a curve representing the product of the two given         M
  221. * curves.                                     M
  222. *                                                                            *
  223. * PARAMETERS:                                                                M
  224. *   Crv1, Crv2:  Two curve to multiply.                         M
  225. *                                                                            *
  226. * RETURN VALUE:                                                              M
  227. *   CagdCrvStruct *:   A curve representing the product of Crv1 and Crv2.    M
  228. *                                                                            *
  229. * KEYWORDS:                                                                  M
  230. *   SymbCrvMultScalar, product, symbolic computation                       M
  231. *****************************************************************************/
  232. CagdCrvStruct *SymbCrvMultScalar(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  233. {
  234.     CagdCrvStruct *PCrv1W, *PCrv1X, *PCrv1Y, *PCrv1Z,
  235.           *PCrv2W, *PCrv2X, *PCrv2Y, *PCrv2Z,
  236.           *TCrv, *ProdCrv;
  237.  
  238.     SymbCrvSplitScalar(Crv1, &PCrv1W, &PCrv1X, &PCrv1Y, &PCrv1Z);
  239.     SymbCrvSplitScalar(Crv2, &PCrv2W, &PCrv2X, &PCrv2Y, &PCrv2Z);
  240.  
  241.     TCrv = SymbCrvMult(PCrv1X, PCrv2X);
  242.     CagdCrvFree(PCrv1X);
  243.     PCrv1X = TCrv;
  244.  
  245.     if (PCrv1Y != NULL) {
  246.     TCrv = SymbCrvMult(PCrv1Y, PCrv2X);
  247.     CagdCrvFree(PCrv1Y);
  248.     PCrv1Y = TCrv;
  249.     }
  250.  
  251.     if (PCrv1Z != NULL) {
  252.     TCrv = SymbCrvMult(PCrv1Z, PCrv2X);
  253.     CagdCrvFree(PCrv1Z);
  254.     PCrv1Z = TCrv;
  255.     }
  256.  
  257.     if (PCrv1W != NULL && PCrv2W != NULL) {
  258.     TCrv = SymbCrvMult(PCrv1W, PCrv2W);
  259.     CagdCrvFree(PCrv1W);
  260.     PCrv1W = TCrv;
  261.     }
  262.     else if (PCrv2W != NULL) {
  263.     PCrv1W = PCrv2W;
  264.     PCrv2W = NULL;
  265.     }
  266.  
  267.     ProdCrv = SymbCrvMergeScalar(PCrv1W, PCrv1X, PCrv1Y, PCrv1Z);
  268.  
  269.     CagdCrvFree(PCrv1W);
  270.     CagdCrvFree(PCrv1X);
  271.     CagdCrvFree(PCrv1Y);
  272.     CagdCrvFree(PCrv1Z);
  273.     CagdCrvFree(PCrv2W);
  274.     CagdCrvFree(PCrv2X);
  275.     CagdCrvFree(PCrv2Y);
  276.     CagdCrvFree(PCrv2Z);
  277.  
  278.     return ProdCrv;
  279. }
  280.  
  281. /*****************************************************************************
  282. * DESCRIPTION:                                                               M
  283. * Given two curves - computes their cross product.                 M
  284. *   Returned curve is a scalar curve representing the cross product of the   M
  285. * two given curves.                                 M
  286. *                                                                            *
  287. * PARAMETERS:                                                                M
  288. *   Crv1, Crv2:  Two curve to multiply and compute a cross product for.      M
  289. *                                                                            *
  290. * RETURN VALUE:                                                              M
  291. *   CagdCrvStruct *:   A scalar curve representing the cross product of      M
  292. *                      Crv1 x Crv2.                                          M
  293. *                                                                            *
  294. * KEYWORDS:                                                                  M
  295. *   SymbCrvCrossProd, product, cross product, symbolic computation           M
  296. *****************************************************************************/
  297. CagdCrvStruct *SymbCrvCrossProd(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  298. {
  299.     CagdCrvStruct *Crv1W, *Crv1X, *Crv1Y, *Crv1Z,
  300.           *Crv2W, *Crv2X, *Crv2Y, *Crv2Z,
  301.           *TCrv1, *TCrv2, *CrossProdCrv,
  302.           *PCrvW, *PCrvX, *PCrvY, *PCrvZ;
  303.     CagdBType
  304.     Crv1New = FALSE,
  305.     Crv2New = FALSE;
  306.  
  307.     if (Crv1 -> GType != CAGD_PT_E3_TYPE && Crv1 -> GType != CAGD_PT_P3_TYPE) {
  308.     Crv1 = CagdCoerceCrvTo(Crv1,
  309.                    CAGD_IS_RATIONAL_CRV(Crv1) ? CAGD_PT_P3_TYPE
  310.                               : CAGD_PT_E3_TYPE);
  311.     Crv1New = TRUE;
  312.     }
  313.     if (Crv2 -> GType != CAGD_PT_E3_TYPE && Crv2 -> GType != CAGD_PT_P3_TYPE) {
  314.     Crv2 = CagdCoerceCrvTo(Crv2,
  315.                    CAGD_IS_RATIONAL_CRV(Crv2) ? CAGD_PT_P3_TYPE
  316.                               : CAGD_PT_E3_TYPE);
  317.     Crv2New = TRUE;
  318.     }
  319.  
  320.     SymbCrvSplitScalar(Crv1, &Crv1W, &Crv1X, &Crv1Y, &Crv1Z);
  321.     SymbCrvSplitScalar(Crv2, &Crv2W, &Crv2X, &Crv2Y, &Crv2Z);
  322.  
  323.     if (Crv1New)
  324.     CagdCrvFree(Crv1);
  325.     if (Crv2New)
  326.     CagdCrvFree(Crv2);
  327.  
  328.     /* Cross product X axis. */
  329.     TCrv1 = SymbCrvMult(Crv1Y, Crv2Z);
  330.     TCrv2 = SymbCrvMult(Crv2Y, Crv1Z);
  331.     PCrvX = SymbCrvSub(TCrv1, TCrv2);
  332.     CagdCrvFree(TCrv2);
  333.     CagdCrvFree(TCrv1);
  334.  
  335.     /* Cross product Y axis. */
  336.     TCrv1 = SymbCrvMult(Crv1Z, Crv2X);
  337.     TCrv2 = SymbCrvMult(Crv2Z, Crv1X);
  338.     PCrvY = SymbCrvSub(TCrv1, TCrv2);
  339.     CagdCrvFree(TCrv2);
  340.     CagdCrvFree(TCrv1);
  341.  
  342.     /* Cross product Z axis. */
  343.     TCrv1 = SymbCrvMult(Crv1X, Crv2Y);
  344.     TCrv2 = SymbCrvMult(Crv2X, Crv1Y);
  345.     PCrvZ = SymbCrvSub(TCrv1, TCrv2);
  346.     CagdCrvFree(TCrv1);
  347.     CagdCrvFree(TCrv2);
  348.  
  349.     /* Cross product W axis. */
  350.     if (Crv1W || Crv2W) {
  351.     if (Crv1W == NULL)
  352.         PCrvW = CagdCrvCopy(Crv2W);
  353.     else if (Crv2W == NULL)
  354.         PCrvW = CagdCrvCopy(Crv1W);
  355.     else
  356.         PCrvW = SymbCrvMult(Crv1W, Crv2W);
  357.     }
  358.     else
  359.     PCrvW = NULL;
  360.  
  361.     CagdCrvFree(Crv1X);
  362.     CagdCrvFree(Crv1Y);
  363.     CagdCrvFree(Crv1Z);
  364.     CagdCrvFree(Crv1W);
  365.  
  366.     CagdCrvFree(Crv2X);
  367.     CagdCrvFree(Crv2Y);
  368.     CagdCrvFree(Crv2Z);
  369.     CagdCrvFree(Crv2W);
  370.  
  371.     if (!CagdMakeCrvsCompatible(&PCrvX, &PCrvY, TRUE, TRUE) ||
  372.     !CagdMakeCrvsCompatible(&PCrvX, &PCrvZ, TRUE, TRUE) ||
  373.     !CagdMakeCrvsCompatible(&PCrvY, &PCrvZ, TRUE, TRUE) ||
  374.     !CagdMakeCrvsCompatible(&PCrvW, &PCrvX, TRUE, TRUE) ||
  375.     !CagdMakeCrvsCompatible(&PCrvW, &PCrvY, TRUE, TRUE) ||
  376.     !CagdMakeCrvsCompatible(&PCrvW, &PCrvZ, TRUE, TRUE))
  377.     SYMB_FATAL_ERROR(SYMB_ERR_CRV_FAIL_CMPT);
  378.  
  379.     CrossProdCrv = SymbCrvMergeScalar(PCrvW, PCrvX, PCrvY, PCrvZ);
  380.     CagdCrvFree(PCrvX);
  381.     CagdCrvFree(PCrvY);
  382.     CagdCrvFree(PCrvZ);
  383.     CagdCrvFree(PCrvW);
  384.  
  385.     return CrossProdCrv;
  386. }
  387.  
  388. /*****************************************************************************
  389. * DESCRIPTION:                                                               M
  390. * Given two curves - multiply them using the quotient product rule:         M
  391. *  X = X1 W2 +/- X2 W1                                 V
  392. *   All provided curves are assumed to be non rational scalar curves.         M
  393. *   Returned is a non rational scalar curve (CAGD_PT_E1_TYPE).             M
  394. *                                                                            *
  395. * PARAMETERS:                                                                M
  396. *   Crv1X:     Numerator of first curve.                                     M
  397. *   Crv1W:     Denominator of first curve.                                   M
  398. *   Crv2X:     Numerator of second curve.                                    M
  399. *   Crv2W:     Denominator of second curve.                                  M
  400. *   OperationAdd:   TRUE for addition, FALSE for subtraction.                M
  401. *                                                                            *
  402. * RETURN VALUE:                                                              M
  403. *   CagdCrvStruct *:  The result of  Crv1X Crv2W +/- Crv2X Crv1W.            M
  404. *                                                                            *
  405. * KEYWORDS:                                                                  M
  406. *   SymbCrvRtnlMult, product, symbolic computation                           M
  407. *****************************************************************************/
  408. CagdCrvStruct *SymbCrvRtnlMult(CagdCrvStruct *Crv1X,
  409.                    CagdCrvStruct *Crv1W,
  410.                    CagdCrvStruct *Crv2X,
  411.                    CagdCrvStruct *Crv2W,
  412.                    CagdBType OperationAdd)
  413. {
  414.     CagdCrvStruct *CTmp1, *CTmp2, *CTmp3;
  415.  
  416.     if (Crv1X == NULL || Crv2X == NULL)
  417.     return NULL;
  418.  
  419.     /* Make the two curves - same order and point type. */
  420.     Crv1X = CagdCrvCopy(Crv1X);
  421.     Crv1W = CagdCrvCopy(Crv1W);
  422.     Crv2X = CagdCrvCopy(Crv2X);
  423.     Crv2W = CagdCrvCopy(Crv2W);
  424.     if (!CagdMakeCrvsCompatible(&Crv1X, &Crv2X, FALSE, FALSE) ||
  425.     !CagdMakeCrvsCompatible(&Crv1W, &Crv2W, FALSE, FALSE) ||
  426.     !CagdMakeCrvsCompatible(&Crv1X, &Crv2W, FALSE, FALSE) ||
  427.     !CagdMakeCrvsCompatible(&Crv1W, &Crv2X, FALSE, FALSE))
  428.     SYMB_FATAL_ERROR(SYMB_ERR_CRV_FAIL_CMPT);
  429.  
  430.     CTmp1 = SymbCrvMult(Crv1X, Crv2W);
  431.     CTmp2 = SymbCrvMult(Crv2X, Crv1W);
  432.     CTmp3 = SymbCrvAddSubAux(CTmp1, CTmp2, OperationAdd);
  433.     CagdCrvFree(CTmp1);
  434.     CagdCrvFree(CTmp2);
  435.  
  436.     CagdCrvFree(Crv1X);
  437.     CagdCrvFree(Crv1W);
  438.     CagdCrvFree(Crv2X);
  439.     CagdCrvFree(Crv2W);
  440.  
  441.     return CTmp3;
  442. }
  443.  
  444. /*****************************************************************************
  445. * DESCRIPTION:                                                               *
  446. * Given two curve - add or subtract them as prescribed by OperationAdd,         *
  447. * coordinatewise.                                       *
  448. *   The two curves are promoted to same type, point type, and order before   *
  449. * addition can take place.                             *
  450. *   Returned is a curve representing their sum or difference.             *
  451. *                                                                            *
  452. * PARAMETERS:                                                                *
  453. *   Crv1, Crv2:    Two curve to subtract coordinatewise.                     *
  454. *   OperationAdd:  TRUE of addition, FALSE for subtraction.                  *
  455. *                                                                            *
  456. * RETURN VALUE:                                                              *
  457. *   CagdCrvStruct *:   The summation or difference of Crv1 and Crv2.         *
  458. *****************************************************************************/
  459. static CagdCrvStruct *SymbCrvAddSubAux(CagdCrvStruct *Crv1,
  460.                        CagdCrvStruct *Crv2,
  461.                        CagdBType OperationAdd)
  462. {
  463.     CagdBType IsNotRational;
  464.     int i, k;
  465.     CagdCrvStruct *SumCrv;
  466.     CagdRType **Points1, **Points2;
  467.  
  468.     /* Make the two curves - same order and point type. */
  469.     Crv1 = CagdCrvCopy(Crv1);
  470.     Crv2 = CagdCrvCopy(Crv2);
  471.     if (!CagdMakeCrvsCompatible(&Crv1, &Crv2, TRUE, TRUE))
  472.     SYMB_FATAL_ERROR(SYMB_ERR_CRV_FAIL_CMPT);
  473.  
  474.     SumCrv = CagdCrvNew(Crv1 -> GType, Crv1 -> PType, k = Crv1 -> Length);
  475.     SumCrv -> Order = Crv1 -> Order;
  476.     if (CAGD_IS_BSPLINE_CRV(SumCrv)) {
  477.     SumCrv->KnotVector = BspKnotCopy(Crv1 -> KnotVector,
  478.                      Crv1 -> Length + Crv1 -> Order);
  479.     }
  480.  
  481.     IsNotRational = !CAGD_IS_RATIONAL_CRV(SumCrv);
  482.     Points1 = Crv1 -> Points;
  483.     Points2 = Crv2 -> Points;
  484.  
  485.     if (IsNotRational) {
  486.     /* Simply add the respective control polygons. */
  487.     SymbMeshAddSub(SumCrv -> Points, Crv1 -> Points, Crv2 -> Points,
  488.                SumCrv -> PType, SumCrv -> Length, OperationAdd);
  489.     }
  490.     else {
  491.     /* Maybe the weights are identical, in which we can still add the   */
  492.     /* the respective control polygons.                    */
  493.     for (i = 0; i < k; i++)
  494.         if (!APX_EQ(Points1[0][i], Points2[0][i])) break;
  495.  
  496.     if (i < k) {
  497.         CagdCrvStruct *Crv1W, *Crv1X, *Crv1Y, *Crv1Z,
  498.               *Crv2W, *Crv2X, *Crv2Y, *Crv2Z,
  499.               *SumCrvW, *SumCrvX, *SumCrvY, *SumCrvZ;
  500.  
  501.         /* Weights are different. Must use the addition of rationals    */
  502.         /* rule ( we invoke SymbCrvMult here):                */
  503.         /*                                    */
  504.         /*  x1     x2   x1 w2 +/- x2 w1                    */
  505.         /*  -- +/- -- = ---------------                    */
  506.         /*  w1     w2        w1 w2                        */
  507.         /*                                    */
  508.         SymbCrvSplitScalar(Crv1, &Crv1W, &Crv1X, &Crv1Y, &Crv1Z);
  509.         SymbCrvSplitScalar(Crv2, &Crv2W, &Crv2X, &Crv2Y, &Crv2Z);
  510.  
  511.         SumCrvW = SymbCrvMult(Crv1W, Crv2W);
  512.         SumCrvX = SymbCrvRtnlMult(Crv1X, Crv1W, Crv2X, Crv2W, OperationAdd);
  513.         SumCrvY = SymbCrvRtnlMult(Crv1Y, Crv1W, Crv2Y, Crv2W, OperationAdd);
  514.         SumCrvZ = SymbCrvRtnlMult(Crv1Z, Crv1W, Crv2Z, Crv2W, OperationAdd);
  515.         CagdCrvFree(Crv1W);
  516.         CagdCrvFree(Crv1X);
  517.         CagdCrvFree(Crv1Y);
  518.         CagdCrvFree(Crv1Z);
  519.         CagdCrvFree(Crv2W);
  520.         CagdCrvFree(Crv2X);
  521.         CagdCrvFree(Crv2Y);
  522.         CagdCrvFree(Crv2Z);
  523.  
  524.         CagdCrvFree(SumCrv);
  525.         SumCrv = SymbCrvMergeScalar(SumCrvW, SumCrvX, SumCrvY, SumCrvZ);
  526.         CagdCrvFree(SumCrvW);
  527.         CagdCrvFree(SumCrvX);
  528.         CagdCrvFree(SumCrvY);
  529.         CagdCrvFree(SumCrvZ);
  530.     }
  531.     else
  532.     {
  533.         /* Simply add respective control polygons (w is just copied). */
  534.         SymbMeshAddSub(SumCrv -> Points, Crv1 -> Points, Crv2 -> Points,
  535.                SumCrv -> PType, SumCrv -> Length, OperationAdd);
  536.     }
  537.     }
  538.  
  539.     CagdCrvFree(Crv1);
  540.     CagdCrvFree(Crv2);
  541.  
  542.     return SumCrv;
  543. }
  544.  
  545. /*****************************************************************************
  546. * DESCRIPTION:                                                               M
  547. * Given a planar curve, compute its enclosed area field curve.             M
  548. *   This has little meaning unless Crv is closed, in which by evaluation     M
  549. * the resulting area filed curve at the end points, the area enclosed by     M
  550. * Crv can be computed.                                                       M
  551. *                                                                            *
  552. * PARAMETERS:                                                                M
  553. *   Crv:       A curve to compute area filed curve for.                 M
  554. *                                                                            *
  555. * RETURN VALUE:                                                              M
  556. *   CagdCrvStruct *:   The area field curve.                                 M
  557. *                                                                            *
  558. * KEYWORDS:                                                                  M
  559. *   SymbCrvEnclosedArea, area, symbolic computation                          M
  560. *****************************************************************************/
  561. CagdCrvStruct *SymbCrvEnclosedArea(CagdCrvStruct *Crv)
  562. {
  563.     CagdVType Trans;
  564.     CagdCrvStruct *CrvX, *CrvY, *CrvZ, *CrvW, *DCrvX, *DCrvY,
  565.     *CTmp1, *CTmp2, *CTmp3;
  566.  
  567.     switch (Crv -> GType) {
  568.     case CAGD_CBEZIER_TYPE:
  569.     case CAGD_CBSPLINE_TYPE:
  570.         break;
  571.     case CAGD_CPOWER_TYPE:
  572.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  573.         return NULL;
  574.     default:
  575.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_CRV);
  576.         return NULL;
  577.     }
  578.  
  579.     /* Using Green's theorem, if C(t1) = C(t2) the area enclosed is equal to */
  580.     /*                                         */
  581.     /*       t2                                     */
  582.     /*        /                                     */
  583.     /*    1  |                                     */
  584.     /*  -  | -x'(t) y(t) + x(t) y'(t) dt                     */
  585.     /*    2  |                                     */
  586.     /*    /                                     */
  587.     /*    t1                                     */
  588.     /*                                         */
  589.     SymbCrvSplitScalar(Crv, &CrvW, &CrvX, &CrvY, &CrvZ);
  590.     if (CrvZ)
  591.         CagdCrvFree(CrvZ);
  592.     if (CrvW) {
  593.     SYMB_FATAL_ERROR(SYMB_ERR_RATIONAL_NO_SUPPORT);
  594.     CagdCrvFree(CrvW);
  595.     }
  596.  
  597.     DCrvX = CagdCrvDerive(CrvX);
  598.     DCrvY = CagdCrvDerive(CrvY);
  599.     CTmp1 = SymbCrvMult(CrvX, DCrvY);
  600.     CTmp2 = SymbCrvMult(DCrvX, CrvY);
  601.     CagdCrvFree(CrvX);
  602.     CagdCrvFree(CrvY);
  603.     CagdCrvFree(DCrvX);
  604.     CagdCrvFree(DCrvY);
  605.     CTmp3 = SymbCrvSub(CTmp1, CTmp2);
  606.     CagdCrvFree(CTmp1);
  607.     CagdCrvFree(CTmp2);
  608.     CTmp1 = CagdCrvIntegrate(CTmp3);
  609.     CagdCrvFree(CTmp3);
  610.  
  611.     /* Scale by a half. */
  612.     Trans[0] = Trans[1] = Trans[2] = 0.0;
  613.     CagdCrvTransform(CTmp1, Trans, 0.5);
  614.  
  615.     return CTmp1;
  616. }
  617.  
  618. /*****************************************************************************
  619. * DESCRIPTION:                                                               M
  620. * Given two surfaces - add them coordinatewise.                     M
  621. *   The two surfaces are promoted to same point type before the             M
  622. * multiplication can take place. Furthermore, order and continuity are         M
  623. * matched as well.                                 M
  624. *                                                                            *
  625. * PARAMETERS:                                                                M
  626. *   Srf1, Srf2:  Two surface to add up coordinatewise.                       M
  627. *                                                                            *
  628. * RETURN VALUE:                                                              M
  629. *   CagdSrfStruct *:   The summation of Srf1 + Srf2 coordinatewise.          M
  630. *                                                                            *
  631. * KEYWORDS:                                                                  M
  632. *   SymbSrfAdd, addition, symbolic computation                               M
  633. *****************************************************************************/
  634. CagdSrfStruct *SymbSrfAdd(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2)
  635. {
  636.     return SymbSrfAddSubAux(Srf1, Srf2, TRUE);
  637. }
  638.  
  639. /*****************************************************************************
  640. * DESCRIPTION:                                                               M
  641. * Given two surfaces - subtract them coordinatewise.                 M
  642. *   The two surfaces are promoted to same point type before the             M
  643. * multiplication can take place. Furthermore, order and continuity are         M
  644. * matched as well.                                 M
  645. *                                                                            *
  646. * PARAMETERS:                                                                M
  647. *   Srf1, Srf2:  Two surface to subtract coordinatewise.                     M
  648. *                                                                            *
  649. * RETURN VALUE:                                                              M
  650. *   CagdSrfStruct *:   The difference of Srf1 - Srf2 coordinatewise.         M
  651. *                                                                            *
  652. * KEYWORDS:                                                                  M
  653. *   SymbSrfSub, subtraction, symbolic computation                            M
  654. *****************************************************************************/
  655. CagdSrfStruct *SymbSrfSub(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2)
  656. {
  657.     return SymbSrfAddSubAux(Srf1, Srf2, FALSE);
  658. }
  659.  
  660. /*****************************************************************************
  661. * DESCRIPTION:                                                               M
  662. * Given two surfaces - multiply them coordinatewise.                 M
  663. *   The two surfaces are promoted to same point type before the          M
  664. * multiplication can take place.                         M
  665. *                                                                            *
  666. * PARAMETERS:                                                                M
  667. *   Srf1, Srf2:  Two surface to multiply coordinatewise.                     M
  668. *                                                                            *
  669. * RETURN VALUE:                                                              M
  670. *   CagdSrfStruct *:   The product of Srf1 * Srf2 coordinatewise.            M
  671. *                                                                            *
  672. * KEYWORDS:                                                                  M
  673. *   SymbSrfMult, product, symbolic computation                               M
  674. *****************************************************************************/
  675. CagdSrfStruct *SymbSrfMult(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2)
  676. {
  677.     CagdSrfStruct
  678.     *ProdSrf = NULL;
  679.  
  680.     Srf1 = CagdSrfCopy(Srf1);
  681.     Srf2 = CagdSrfCopy(Srf2);
  682.     if (!CagdMakeSrfsCompatible(&Srf1, &Srf2, FALSE, FALSE, FALSE, FALSE))
  683.     SYMB_FATAL_ERROR(SYMB_ERR_SRF_FAIL_CMPT);
  684.  
  685.     switch (Srf1 -> GType) {
  686.     case CAGD_SBEZIER_TYPE:
  687.         ProdSrf = BzrSrfMult(Srf1, Srf2);
  688.         break;
  689.     case CAGD_SBSPLINE_TYPE:
  690.         ProdSrf = BspSrfMult(Srf1, Srf2);
  691.         break;
  692.     case CAGD_SPOWER_TYPE:
  693.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  694.         break;
  695.     default:
  696.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_SRF);
  697.         break;
  698.     }
  699.  
  700.     CagdSrfFree(Srf1);
  701.     CagdSrfFree(Srf2);
  702.  
  703.     return ProdSrf;
  704. }
  705.  
  706. /*****************************************************************************
  707. * DESCRIPTION:                                                               M
  708. * Given a scalar surface, returns a scalar surface representing the         M
  709. * reciprocal values, by making it rational (if was not one) and flipping     M
  710. * the numerator and the denominator.                         M
  711. *                                                                            *
  712. * PARAMETERS:                                                                M
  713. *   Srf:       A scalar surface to compute a reciprocal value for.           M
  714. *                                                                            *
  715. * RETURN VALUE:                                                              M
  716. *   CagdSrfStruct *:   A rational scalar surface that is equalto the         M
  717. *                      reciprocal value of Srf.                              M
  718. * KEYWORDS:                                                                  M
  719. *   SymbSrfInvert, division, symbolic computation, reciprocal value          M
  720. *****************************************************************************/
  721. CagdSrfStruct *SymbSrfInvert(CagdSrfStruct *Srf)
  722. {
  723.     int i;
  724.     CagdRType *R, **Points;
  725.  
  726.     Srf = CagdSrfCopy(Srf);
  727.     Points = Srf -> Points;
  728.  
  729.     switch (Srf -> PType) {
  730.     case CAGD_PT_E1_TYPE:
  731.         Points[0] = Points[1];
  732.         Points[1] = R = (CagdRType *) IritMalloc(sizeof(CagdRType) *
  733.                          Srf -> ULength * Srf -> VLength);
  734.         for (i = 0; i < Srf -> ULength * Srf -> VLength; i++)
  735.         *R++ = 1.0;
  736.         Srf -> PType = CAGD_PT_P1_TYPE;
  737.         break;
  738.     case CAGD_PT_P1_TYPE:
  739.         R = Points[0];
  740.         Points[0] = Points[1];
  741.         Points[1] = R;
  742.         break;
  743.     default:
  744.         SYMB_FATAL_ERROR(SYMB_ERR_UNSUPPORT_PT);
  745.         break;
  746.     }
  747.  
  748.     return Srf;
  749. }
  750.  
  751. /*****************************************************************************
  752. * DESCRIPTION:                                                               M
  753. * Given a surface, scale it by Scale.                         M
  754. *                                                                            *
  755. * PARAMETERS:                                                                M
  756. *   Srf:      A surface to scale by magnitude Scale.                         M
  757. *   Scale:    Scaling factor.                                                M
  758. *                                                                            *
  759. * RETURN VALUE:                                                              M
  760. *   CagdSrfStruct *:   A surfaces scaled by Scale compared to Srf.           M
  761. *                                                                            *
  762. * KEYWORDS:                                                                  M
  763. *   SymbSrfScalarScale, scaling, symbolic computation                        M
  764. *****************************************************************************/
  765. CagdSrfStruct *SymbSrfScalarScale(CagdSrfStruct *Srf, CagdRType Scale)
  766. {
  767.     int i;
  768.     CagdRType *R;
  769.  
  770.     Srf = CagdSrfCopy(Srf);
  771.  
  772.     switch (Srf -> PType) {
  773.     case CAGD_PT_P1_TYPE:
  774.     case CAGD_PT_E1_TYPE:
  775.         for (i = 0, R = Srf -> Points[1];
  776.          i < Srf -> ULength * Srf -> VLength;
  777.          i++)
  778.         *R++ *= Scale;
  779.         break;
  780.     default:
  781.         SYMB_FATAL_ERROR(SYMB_ERR_UNSUPPORT_PT);
  782.         break;
  783.     }
  784.  
  785.     return Srf;
  786. }
  787.  
  788. /*****************************************************************************
  789. * DESCRIPTION:                                                               M
  790. * Given two surfaces - computes their dot product.                 M
  791. *   Returned surface is a scalar surface representing the dot product of the M
  792. * two given surfaces.                                 M
  793. *                                                                            *
  794. * PARAMETERS:                                                                M
  795. *   Srf1, Srf2:  Two surface to multiply and compute a dot product for.      M
  796. *                                                                            *
  797. * RETURN VALUE:                                                              M
  798. *   CagdSrfStruct *:   A scalar surface representing the dot product of      M
  799. *                      Srf1 . Srf2.                                          M
  800. *                                                                            *
  801. * KEYWORDS:                                                                  M
  802. *   SymbSrfDotProd, product, dot product, symbolic computation               M
  803. *****************************************************************************/
  804. CagdSrfStruct *SymbSrfDotProd(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2)
  805. {
  806.     CagdSrfStruct *PSrfW, *PSrfX, *PSrfY, *PSrfZ, *TSrf1, *TSrf2, *DotProdSrf,
  807.     *ProdSrf = SymbSrfMult(Srf1, Srf2);
  808.  
  809.     SymbSrfSplitScalar(ProdSrf, &PSrfW, &PSrfX, &PSrfY, &PSrfZ);
  810.     CagdSrfFree(ProdSrf);
  811.  
  812.     if (PSrfY != NULL) {
  813.     TSrf1 = SymbSrfAdd(PSrfX, PSrfY);
  814.     CagdSrfFree(PSrfX);
  815.     CagdSrfFree(PSrfY);
  816.     }
  817.     else
  818.     TSrf1 = PSrfX;
  819.  
  820.     if (PSrfZ != NULL) {
  821.     TSrf2 = SymbSrfAdd(TSrf1, PSrfZ);
  822.     CagdSrfFree(TSrf1);
  823.     CagdSrfFree(PSrfZ);
  824.     TSrf1 = TSrf2;
  825.     }
  826.  
  827.     DotProdSrf = SymbSrfMergeScalar(PSrfW, TSrf1, NULL, NULL);
  828.     CagdSrfFree(PSrfW);
  829.     CagdSrfFree(TSrf1);
  830.  
  831.     return DotProdSrf;
  832. }
  833.  
  834. /*****************************************************************************
  835. * DESCRIPTION:                                                               M
  836. * Given two surfaces - computes their cross product.                 M
  837. *   Returned surface is a scalar surface representing the cross product of   M
  838. * the two given surfaces.                             M
  839. *                                                                            *
  840. * PARAMETERS:                                                                M
  841. *   Srf1, Srf2:  Two surface to multiply and compute a cross product for.    M
  842. *                                                                            *
  843. * RETURN VALUE:                                                              M
  844. *   CagdSrfStruct *:   A scalar surface representing the cross product of    M
  845. *                      Srf1 x Srf2.                                          M
  846. *                                                                            *
  847. * KEYWORDS:                                                                  M
  848. *   SymbSrfCrossProd, product, cross product, symbolic computation           M
  849. *****************************************************************************/
  850. CagdSrfStruct *SymbSrfCrossProd(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2)
  851. {
  852.     CagdSrfStruct *Srf1W, *Srf1X, *Srf1Y, *Srf1Z,
  853.           *Srf2W, *Srf2X, *Srf2Y, *Srf2Z,
  854.           *TSrf1, *TSrf2, *CrossProdSrf,
  855.     *PSrfW = NULL,
  856.     *PSrfX = NULL,
  857.     *PSrfY = NULL,
  858.     *PSrfZ = NULL;
  859.  
  860.     SymbSrfSplitScalar(Srf1, &Srf1W, &Srf1X, &Srf1Y, &Srf1Z);
  861.     SymbSrfSplitScalar(Srf2, &Srf2W, &Srf2X, &Srf2Y, &Srf2Z);
  862.  
  863.     if (Srf1X == NULL || Srf1Y == NULL || Srf2X == NULL || Srf2Y == NULL)
  864.     SYMB_FATAL_ERROR(SYMB_ERR_NO_CROSS_PROD);
  865.  
  866.     /* Cross product X axis. */
  867.     TSrf1 = Srf2Z ? SymbSrfMult(Srf1Y, Srf2Z) : NULL;
  868.     TSrf2 = Srf1Z ? SymbSrfMult(Srf2Y, Srf1Z) : NULL;
  869.  
  870.     if (TSrf1) {
  871.     if (TSrf2) {
  872.         PSrfX = SymbSrfSub(TSrf1, TSrf2);
  873.         CagdSrfFree(TSrf2);
  874.     }
  875.     CagdSrfFree(TSrf1);
  876.     }
  877.  
  878.     /* Cross product Y axis. */
  879.     TSrf1 = Srf1Z ? SymbSrfMult(Srf1Z, Srf2X) : NULL;
  880.     TSrf2 = Srf2Z ? SymbSrfMult(Srf2Z, Srf1X) : NULL;
  881.     if (TSrf1) {
  882.     if (TSrf2) {
  883.         PSrfY = SymbSrfSub(TSrf1, TSrf2);
  884.         CagdSrfFree(TSrf2);
  885.     }
  886.     CagdSrfFree(TSrf1);
  887.     }
  888.  
  889.     /* Cross product Z axis. */
  890.     TSrf1 = SymbSrfMult(Srf1X, Srf2Y);
  891.     TSrf2 = SymbSrfMult(Srf2X, Srf1Y);
  892.     PSrfZ = SymbSrfSub(TSrf1, TSrf2);
  893.     CagdSrfFree(TSrf1);
  894.     CagdSrfFree(TSrf2);
  895.  
  896.     /* Cross product W axis. */
  897.     if (Srf1W || Srf2W) {
  898.     if (Srf1W == NULL)
  899.         PSrfW = CagdSrfCopy(Srf2W);
  900.     else if (Srf2W == NULL)
  901.         PSrfW = CagdSrfCopy(Srf1W);
  902.     else
  903.         PSrfW = SymbSrfMult(Srf1W, Srf2W);
  904.     }
  905.  
  906.     CagdSrfFree(Srf1X);
  907.     CagdSrfFree(Srf1Y);
  908.     CagdSrfFree(Srf1Z);
  909.     CagdSrfFree(Srf1W);
  910.  
  911.     CagdSrfFree(Srf2X);
  912.     CagdSrfFree(Srf2Y);
  913.     CagdSrfFree(Srf2Z);
  914.     CagdSrfFree(Srf2W);
  915.  
  916.     if (!CagdMakeSrfsCompatible(&PSrfW, &PSrfX, TRUE, TRUE, TRUE, TRUE) ||
  917.     !CagdMakeSrfsCompatible(&PSrfW, &PSrfY, TRUE, TRUE, TRUE, TRUE) ||
  918.     !CagdMakeSrfsCompatible(&PSrfW, &PSrfZ, TRUE, TRUE, TRUE, TRUE))
  919.     SYMB_FATAL_ERROR(SYMB_ERR_SRF_FAIL_CMPT);
  920.  
  921.     CrossProdSrf = SymbSrfMergeScalar(PSrfW, PSrfX, PSrfY, PSrfZ);
  922.     CagdSrfFree(PSrfX);
  923.     CagdSrfFree(PSrfY);
  924.     CagdSrfFree(PSrfZ);
  925.     CagdSrfFree(PSrfW);
  926.  
  927.     return CrossProdSrf;
  928. }
  929.  
  930. /*****************************************************************************
  931. * DESCRIPTION:                                                               M
  932. * Given two surfaces - multiply them using the quotient product rule:         M
  933. *  X = X1 W2 +/- X2 W1                                 V
  934. *   All provided surfaces are assumed to be non rational scalar surfaces.    M
  935. *   Returned is a non rational scalar surface (CAGD_PT_E1_TYPE).         M
  936. *                                                                            *
  937. * PARAMETERS:                                                                M
  938. *   Srf1X:     Numerator of first surface.                                   M
  939. *   Srf1W:     Denominator of first surface.                                 M
  940. *   Srf2X:     Numerator of second surface.                                  M
  941. *   Srf2W:     Denominator of second surface.                                M
  942. *   OperationAdd:   TRUE for addition, FALSE for subtraction.                M
  943. *                                                                            *
  944. * RETURN VALUE:                                                              M
  945. *   CagdSrfStruct *:  The result of  Srf1X Srf2W +/- Srf2X Srf1W.            M
  946. *                                                                            *
  947. * KEYWORDS:                                                                  M
  948. *   SymbSrfRtnlMult, product, symbolic computation                           M
  949. *****************************************************************************/
  950. CagdSrfStruct *SymbSrfRtnlMult(CagdSrfStruct *Srf1X,
  951.                    CagdSrfStruct *Srf1W,
  952.                    CagdSrfStruct *Srf2X,
  953.                    CagdSrfStruct *Srf2W,
  954.                    CagdBType OperationAdd)
  955. {
  956.     CagdSrfStruct *CTmp1, *CTmp2, *CTmp3;
  957.  
  958.     /* Make the two surfaces - same order and point type. */
  959.     Srf1X = CagdSrfCopy(Srf1X);
  960.     Srf1W = CagdSrfCopy(Srf1W);
  961.     Srf2X = CagdSrfCopy(Srf2X);
  962.     Srf2W = CagdSrfCopy(Srf2W);
  963.     if (!CagdMakeSrfsCompatible(&Srf1X, &Srf2X, FALSE, FALSE, FALSE, FALSE) ||
  964.     !CagdMakeSrfsCompatible(&Srf1W, &Srf2W, FALSE, FALSE, FALSE, FALSE) ||
  965.     !CagdMakeSrfsCompatible(&Srf1X, &Srf2W, FALSE, FALSE, FALSE, FALSE) ||
  966.     !CagdMakeSrfsCompatible(&Srf1W, &Srf2X, FALSE, FALSE, FALSE, FALSE))
  967.     SYMB_FATAL_ERROR(SYMB_ERR_SRF_FAIL_CMPT);
  968.  
  969.     CTmp1 = SymbSrfMult(Srf1X, Srf2W);
  970.     CTmp2 = SymbSrfMult(Srf2X, Srf1W);
  971.     CTmp3 = SymbSrfAddSubAux(CTmp1, CTmp2, OperationAdd);
  972.     CagdSrfFree(CTmp1);
  973.     CagdSrfFree(CTmp2);
  974.  
  975.     CagdSrfFree(Srf1X);
  976.     CagdSrfFree(Srf1W);
  977.     CagdSrfFree(Srf2X);
  978.     CagdSrfFree(Srf2W);
  979.  
  980.     return CTmp3;
  981. }
  982.  
  983. /*****************************************************************************
  984. * DESCRIPTION:                                                               M
  985. * Given a surface - compute its unnormalized norrmal vectorfield surface, as M
  986. * the cross product if this partial derivatives.                             M
  987. *                                                                            *
  988. * PARAMETERS:                                                                M
  989. *   Srf:       To compute an unnormalized normal vector field for.           M
  990. *                                                                            *
  991. * RETURN VALUE:                                                              M
  992. *   CagdSrfStruct *:   A vector field representing the unnormalized normal   M
  993. *                      vector field of Srf.                                  M
  994. *                                                                            *
  995. * KEYWORDS:                                                                  M
  996. *   SymbSrfNormalSrf, normal, symbolic computation                           M
  997. *****************************************************************************/
  998. CagdSrfStruct *SymbSrfNormalSrf(CagdSrfStruct *Srf)
  999. {
  1000.     CagdSrfStruct
  1001.     *SrfDU = CagdSrfDerive(Srf, CAGD_CONST_U_DIR),
  1002.     *SrfDV = CagdSrfDerive(Srf, CAGD_CONST_V_DIR),
  1003.     *NormalSrf = SymbSrfCrossProd(SrfDV, SrfDU);
  1004.  
  1005.     CagdSrfFree(SrfDU);
  1006.     CagdSrfFree(SrfDV);
  1007.  
  1008.     return NormalSrf;
  1009. }
  1010.  
  1011. /*****************************************************************************
  1012. * DESCRIPTION:                                                               *
  1013. * Given two surface - add or subtract them as prescribed by OperationAdd,    *
  1014. * coordinatewise.                                       *
  1015. *   The two surfaces are promoted to same type, point type, and order before *
  1016. * addition can take place.                             *
  1017. *   Returned is a surface representing their sum or difference.             *
  1018. *                                                                            *
  1019. * PARAMETERS:                                                                *
  1020. *   Srf1, Srf2:    Two surface to subtract coordinatewise.                   *
  1021. *   OperationAdd:  TRUE of addition, FALSE for subtraction.                  *
  1022. *                                                                            *
  1023. * RETURN VALUE:                                                              *
  1024. *   CagdSrfStruct *:   The summation or difference of Srf1 and Srf2.         *
  1025. *****************************************************************************/
  1026. static CagdSrfStruct *SymbSrfAddSubAux(CagdSrfStruct *Srf1,
  1027.                        CagdSrfStruct *Srf2,
  1028.                        CagdBType OperationAdd)
  1029. {
  1030.  
  1031.     CagdBType IsNotRational;
  1032.     int i, Len;
  1033.     CagdSrfStruct *SumSrf;
  1034.     CagdRType **Points1, **Points2;
  1035.  
  1036.     /* Make the two surfaces - same order and point type. */
  1037.     Srf1 = CagdSrfCopy(Srf1);
  1038.     Srf2 = CagdSrfCopy(Srf2);
  1039.     if (!CagdMakeSrfsCompatible(&Srf1, &Srf2, TRUE, TRUE, TRUE, TRUE))
  1040.     SYMB_FATAL_ERROR(SYMB_ERR_SRF_FAIL_CMPT);
  1041.  
  1042.     Len = Srf1 -> ULength * Srf1 ->VLength;
  1043.     SumSrf = CagdSrfNew(Srf1 -> GType, Srf1 -> PType,
  1044.             Srf1 -> ULength, Srf1 ->VLength);
  1045.     SumSrf -> UOrder = Srf1 -> UOrder;
  1046.     SumSrf -> VOrder = Srf1 -> VOrder;
  1047.     if (CAGD_IS_BSPLINE_SRF(SumSrf)) {
  1048.     SumSrf -> UKnotVector = BspKnotCopy(Srf1 -> UKnotVector,
  1049.                         Srf1 -> ULength + Srf1 -> UOrder);
  1050.     SumSrf -> VKnotVector = BspKnotCopy(Srf1 -> VKnotVector,
  1051.                         Srf1 -> VLength + Srf1 -> VOrder);
  1052.     }
  1053.  
  1054.     IsNotRational = !CAGD_IS_RATIONAL_SRF(SumSrf);
  1055.     Points1 = Srf1 -> Points;
  1056.     Points2 = Srf2 -> Points;
  1057.  
  1058.     if (IsNotRational) {
  1059.     /* Simply add the respective control polygons. */
  1060.     SymbMeshAddSub(SumSrf -> Points, Srf1 -> Points, Srf2 -> Points,
  1061.                SumSrf -> PType, Len, OperationAdd);
  1062.     }
  1063.     else {
  1064.     /* Maybe the weights are identical, in which we can still add the   */
  1065.     /* the respective control polygons.                    */
  1066.     for (i = 0; i < Len; i++)
  1067.         if (!APX_EQ(Points1[0][i], Points2[0][i])) break;
  1068.  
  1069.     if (i < Len) {
  1070.         CagdSrfStruct *Srf1W, *Srf1X, *Srf1Y, *Srf1Z,
  1071.               *Srf2W, *Srf2X, *Srf2Y, *Srf2Z,
  1072.               *SumSrfW, *SumSrfX, *SumSrfY, *SumSrfZ;
  1073.  
  1074.         /* Weights are different. Must use the addition of rationals    */
  1075.         /* rule ( we invoke SymbSrfMult here):                */
  1076.         /*                                    */
  1077.         /*  x1     x2   x1 w2 +/- x2 w1                    */
  1078.         /*  -- +/- -- = ---------------                    */
  1079.         /*  w1     w2        w1 w2                        */
  1080.         /*                                    */
  1081.         SymbSrfSplitScalar(Srf1, &Srf1W, &Srf1X, &Srf1Y, &Srf1Z);
  1082.         SymbSrfSplitScalar(Srf2, &Srf2W, &Srf2X, &Srf2Y, &Srf2Z);
  1083.  
  1084.         SumSrfW = SymbSrfMult(Srf1W, Srf2W);
  1085.         SumSrfX = SymbSrfRtnlMult(Srf1X, Srf1W, Srf2X, Srf2W, OperationAdd);
  1086.         SumSrfY = SymbSrfRtnlMult(Srf1Y, Srf1W, Srf2Y, Srf2W, OperationAdd);
  1087.         SumSrfZ = SymbSrfRtnlMult(Srf1Z, Srf1W, Srf2Z, Srf2W, OperationAdd);
  1088.         CagdSrfFree(Srf1W);
  1089.         CagdSrfFree(Srf1X);
  1090.         CagdSrfFree(Srf1Y);
  1091.         CagdSrfFree(Srf1Z);
  1092.         CagdSrfFree(Srf2W);
  1093.         CagdSrfFree(Srf2X);
  1094.         CagdSrfFree(Srf2Y);
  1095.         CagdSrfFree(Srf2Z);
  1096.  
  1097.         CagdSrfFree(SumSrf);
  1098.         SumSrf = SymbSrfMergeScalar(SumSrfW, SumSrfX, SumSrfY, SumSrfZ);
  1099.         CagdSrfFree(SumSrfW);
  1100.         CagdSrfFree(SumSrfX);
  1101.         CagdSrfFree(SumSrfY);
  1102.         CagdSrfFree(SumSrfZ);
  1103.     }
  1104.     else
  1105.     {
  1106.         /* Simply add respective control polygons (w is just copied). */
  1107.         SymbMeshAddSub(SumSrf -> Points, Srf1 -> Points, Srf2 -> Points,
  1108.                SumSrf -> PType, Len, OperationAdd);
  1109.     }
  1110.     }
  1111.  
  1112.     CagdSrfFree(Srf1);
  1113.     CagdSrfFree(Srf2);
  1114.  
  1115.     return SumSrf;
  1116. }
  1117.  
  1118. /******************************************************************************
  1119. * DESCRIPTION:                                                               M
  1120. * Given two control polygons/meshes - add them coordinatewise.             M
  1121. * If mesh is rational, weights are assumed identical and are just copied.    M
  1122. *                                                                            *
  1123. * PARAMETERS:                                                                M
  1124. *   DestPoints:    Where addition or difference result should go to.         M
  1125. *   Points1:       First control polygon/mesh.                               M
  1126. *   Points2:       Second control polygon/mesh.                              M
  1127. *   PType:         Type of points we are dealing with.                       M
  1128. *   Size:          Length of each vector in Points1/2.                       M
  1129. *   OperationAdd:  TRUE of addition, FALSE for subtraction.                  M
  1130. *                                                                            *
  1131. * RETURN VALUE:                                                              M
  1132. *   void                                                                     M
  1133. *                                                                            *
  1134. * KEYWORDS:                                                                  M
  1135. *   SymbMeshAddSub, addition, subtraction, symbolic computation              M
  1136. *****************************************************************************/
  1137. void SymbMeshAddSub(CagdRType **DestPoints,
  1138.             CagdRType **Points1,
  1139.             CagdRType **Points2,
  1140.             CagdPointType PType,
  1141.             int Size,
  1142.             CagdBType OperationAdd)
  1143. {
  1144.     CagdBType
  1145.     IsRational = CAGD_IS_RATIONAL_PT(PType);
  1146.     int i, j,
  1147.     NumCoords = CAGD_NUM_OF_PT_COORD(PType);
  1148.  
  1149.     for (i = 1; i <= NumCoords; i++) {
  1150.     CagdRType
  1151.         *DPts = DestPoints[i],
  1152.         *Pts1 = Points1[i],
  1153.         *Pts2 = Points2[i];
  1154.  
  1155.     for (j = 0; j < Size; j++)
  1156.         *DPts++ = OperationAdd ? *Pts1++ + *Pts2++ : *Pts1++ - *Pts2++;
  1157.     }
  1158.  
  1159.     if (IsRational) {     /* Copy the weights (should be identical in both). */
  1160.     CagdRType
  1161.         *DPts = DestPoints[0],
  1162.         *Pts1 = Points1[0],
  1163.         *Pts2 = Points2[0];
  1164.  
  1165.     for (j = 0; j < Size; j++) {
  1166.         if (!APX_EQ(*Pts1, *Pts2))
  1167.         SYMB_FATAL_ERROR(SYMB_ERR_W_NOT_SAME);
  1168.         *DPts++ = *Pts1++;
  1169.         Pts2++;
  1170.     }
  1171.     }
  1172. }
  1173.  
  1174. /*****************************************************************************
  1175. * DESCRIPTION:                                                               M
  1176. * Given a curve splits it to its scalar component curves. Ignores all         M
  1177. * dimensions beyond the third, Z, dimension.                     M
  1178. *                                                                            *
  1179. * PARAMETERS:                                                                M
  1180. *   Crv:      Curve to split.                                                M
  1181. *   CrvW:     The weight component of Crv, if have any.                      M
  1182. *   CrvX:     The X component of Crv.                                        M
  1183. *   CrvY:     The Y component of Crv, if have any.                           M
  1184. *   CrvZ:     The Z component of Crv, if have any.                           M
  1185. *                                                                            *
  1186. * RETURN VALUE:                                                              M
  1187. *   void                                                                     M
  1188. *                                                                            *
  1189. * KEYWORDS:                                                                  M
  1190. *   SymbCrvSplitScalar, split, symbolic computation                          M
  1191. *****************************************************************************/
  1192. void SymbCrvSplitScalar(CagdCrvStruct *Crv,
  1193.             CagdCrvStruct **CrvW,
  1194.             CagdCrvStruct **CrvX,
  1195.             CagdCrvStruct **CrvY,
  1196.             CagdCrvStruct **CrvZ)
  1197. {
  1198.     CagdBType
  1199.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  1200.     int i,
  1201.     Length = Crv -> Length,
  1202.     NumCoords = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  1203.     CagdCrvStruct
  1204.     *Crvs[CAGD_MAX_PT_SIZE];
  1205.  
  1206.     for (i = 0; i < CAGD_MAX_PT_SIZE; i++)
  1207.     Crvs[i] = NULL;
  1208.  
  1209.     for (i = IsNotRational; i <= NumCoords; i++) {
  1210.     Crvs[i] = CagdCrvNew(Crv -> GType, CAGD_PT_E1_TYPE, Length);
  1211.     Crvs[i] -> Order = Crv -> Order;
  1212.     if (Crv -> KnotVector != NULL)
  1213.         Crvs[i] -> KnotVector = BspKnotCopy(Crv -> KnotVector,
  1214.                         Crv -> Length + Crv -> Order);
  1215.  
  1216.     SYMB_GEN_COPY(Crvs[i] -> Points[1], Crv -> Points[i],
  1217.               sizeof(CagdRType) * Length);
  1218.     }
  1219.  
  1220.     *CrvW = Crvs[0];
  1221.     *CrvX = Crvs[1];
  1222.     *CrvY = Crvs[2];
  1223.     *CrvZ = Crvs[3];
  1224. }
  1225.  
  1226. /*****************************************************************************
  1227. * DESCRIPTION:                                                               M
  1228. * Given a set of scalar curves, treat them as coordinates into a new curve.  M
  1229. *   Assumes at least CrvX is not NULL in which a scalar curve is returned.   M
  1230. *   Assumes CrvX/Y/Z/W are either E1 or P1 in which the weights are assumed  M
  1231. * to be identical and can be ignored if CrvW exists or copied otheriwse.     M
  1232. *                                                                            *
  1233. * PARAMETERS:                                                                M
  1234. *   CrvW:     The weight component of new constructed curve, if have any.    M
  1235. *   CrvX:     The X component of new constructed curve.                      M
  1236. *   CrvY:     The Y component of new constructed curve, if have any.         M
  1237. *   CrvZ:     The Z component of new constructed curve, if have any.         M
  1238. *                                                                            *
  1239. * RETURN VALUE:                                                              M
  1240. *   CagdCrvStruct *:   A new curve constructed from given scalar curves.     M
  1241. *                                                                            *
  1242. * KEYWORDS:                                                                  M
  1243. *   SymbCrvMergeScalar, merge, symbolic computation                          M
  1244. *****************************************************************************/
  1245. CagdCrvStruct *SymbCrvMergeScalar(CagdCrvStruct *CrvW,
  1246.                   CagdCrvStruct *CrvX,
  1247.                   CagdCrvStruct *CrvY,
  1248.                   CagdCrvStruct *CrvZ)
  1249. {
  1250.     CagdBType
  1251.     WeightCopied = FALSE,
  1252.     IsRational = CrvW != NULL;
  1253.     int i,
  1254.     Length = CrvX -> Length,
  1255.     NumCoords = (CrvX != NULL) + (CrvY != NULL) + (CrvZ != NULL);
  1256.     CagdPointType
  1257.     PType = CAGD_MAKE_PT_TYPE(IsRational, NumCoords);
  1258.     CagdCrvStruct *Crvs[CAGD_MAX_PT_SIZE],
  1259.     *Crv = CagdCrvNew(CrvX -> GType, PType, Length);
  1260.  
  1261.     Crvs[0] = CrvW;
  1262.     Crvs[1] = CrvX;
  1263.     Crvs[2] = CrvY;
  1264.     Crvs[3] = CrvZ;
  1265.  
  1266.     Crv -> Order = CrvX -> Order;
  1267.     if (CrvX -> KnotVector != NULL)
  1268.     Crv -> KnotVector = BspKnotCopy(CrvX -> KnotVector,
  1269.                     Length + CrvX -> Order);
  1270.  
  1271.     for (i = !IsRational; i <= NumCoords; i++) {
  1272.     if (Crvs[i] != NULL) {
  1273.         if (Crvs[i] -> PType != CAGD_PT_E1_TYPE) {
  1274.         if (Crvs[i] -> PType != CAGD_PT_P1_TYPE)
  1275.             SYMB_FATAL_ERROR(SYMB_ERR_SCALAR_EXPECTED);
  1276.         else if (CrvW == NULL && WeightCopied == FALSE) {
  1277.             SYMB_GEN_COPY(Crv -> Points[0], Crvs[i] -> Points[0],
  1278.                   sizeof(CagdRType) * Length);
  1279.             WeightCopied = TRUE;
  1280.         }
  1281.         }
  1282.  
  1283.         SYMB_GEN_COPY(Crv -> Points[i], Crvs[i] -> Points[1],
  1284.               sizeof(CagdRType) * Length);
  1285.     }
  1286.     }
  1287.  
  1288.     return Crv;
  1289. }
  1290.  
  1291. /*****************************************************************************
  1292. * DESCRIPTION:                                                               M
  1293. * Given a surface splits it to its scalar component surfaces. Ignores all    M
  1294. * dimensions beyond the third, Z, dimension.                     M
  1295. *                                                                            *
  1296. * PARAMETERS:                                                                M
  1297. *   Srf:      Surface to split.                                              M
  1298. *   SrfW:     The weight component of Srf, if have any.                      M
  1299. *   SrfX:     The X component of Srf.                                        M
  1300. *   SrfY:     The Y component of Srf, if have any.                           M
  1301. *   SrfZ:     The Z component of Srf, if have any.                           M
  1302. *                                                                            *
  1303. * RETURN VALUE:                                                              M
  1304. *   void                                                                     M
  1305. *                                                                            *
  1306. * KEYWORDS:                                                                  M
  1307. *   SymbSrfSplitScalar, split, symbolic computation                          M
  1308. *****************************************************************************/
  1309. void SymbSrfSplitScalar(CagdSrfStruct *Srf,
  1310.             CagdSrfStruct **SrfW,
  1311.             CagdSrfStruct **SrfX,
  1312.             CagdSrfStruct **SrfY,
  1313.             CagdSrfStruct **SrfZ)
  1314. {
  1315.     CagdBType
  1316.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  1317.     int i,
  1318.     ULength = Srf -> ULength,
  1319.     VLength = Srf -> VLength,
  1320.     NumCoords = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  1321.     CagdSrfStruct
  1322.     *Srfs[CAGD_MAX_PT_SIZE];
  1323.  
  1324.     for (i = 0; i < CAGD_MAX_PT_SIZE; i++)
  1325.     Srfs[i] = NULL;
  1326.  
  1327.     for (i = IsNotRational; i <= NumCoords; i++) {
  1328.     Srfs[i] = CagdSrfNew(Srf -> GType, CAGD_PT_E1_TYPE, ULength, VLength);
  1329.     Srfs[i] -> UOrder = Srf -> UOrder;
  1330.     Srfs[i] -> VOrder = Srf -> VOrder;
  1331.     if (Srf -> UKnotVector != NULL)
  1332.         Srfs[i] -> UKnotVector = BspKnotCopy(Srf -> UKnotVector,
  1333.                          ULength + Srf -> UOrder);
  1334.     if (Srf -> VKnotVector != NULL)
  1335.         Srfs[i] -> VKnotVector = BspKnotCopy(Srf -> VKnotVector,
  1336.                          VLength + Srf -> VOrder);
  1337.  
  1338.     SYMB_GEN_COPY(Srfs[i] -> Points[1], Srf -> Points[i],
  1339.               sizeof(CagdRType) * Srf -> ULength * Srf -> VLength);
  1340.     }
  1341.  
  1342.     *SrfW = Srfs[0];
  1343.     *SrfX = Srfs[1];
  1344.     *SrfY = Srfs[2];
  1345.     *SrfZ = Srfs[3];
  1346. }
  1347.  
  1348. /*****************************************************************************
  1349. * DESCRIPTION:                                                               M
  1350. * Given a set of scalar surfaces, treat them as coordinates into a new         M
  1351. * surface.                                     M
  1352. *   Assumes at least SrfX is not NULL in which a scalar surface is returned.  M
  1353. *   Assumes SrfX/Y/Z/W are either E1 or P1 in which the weights are assumed  M
  1354. * to be identical and can be ignored if SrfW exists or copied otheriwse.     M
  1355. *                                                                            *
  1356. * PARAMETERS:                                                                M
  1357. *   SrfW:     The weight component of new constructed surface, if have any.  M
  1358. *   SrfX:     The X component of new constructed surface.                    M
  1359. *   SrfY:     The Y component of new constructed surface, if have any.       M
  1360. *   SrfZ:     The Z component of new constructed surface, if have any.       M
  1361. *                                                                            *
  1362. * RETURN VALUE:                                                              M
  1363. *   CagdSrfStruct *:   A new surface constructed from given scalar surfaces. M
  1364. *                                                                            *
  1365. * KEYWORDS:                                                                  M
  1366. *   SymbSrfMergeScalar, merge, symbolic computation                          M
  1367. *****************************************************************************/
  1368. CagdSrfStruct *SymbSrfMergeScalar(CagdSrfStruct *SrfW,
  1369.                   CagdSrfStruct *SrfX,
  1370.                   CagdSrfStruct *SrfY,
  1371.                   CagdSrfStruct *SrfZ)
  1372. {
  1373.     CagdBType
  1374.     WeightCopied = FALSE,
  1375.     IsRational = SrfW != NULL;
  1376.     int i,
  1377.     ULength = SrfX -> ULength,
  1378.     VLength = SrfX -> VLength,
  1379.     NumCoords = (SrfX != NULL) + (SrfY != NULL) + (SrfZ != NULL);
  1380.     CagdPointType
  1381.     PType = CAGD_MAKE_PT_TYPE(IsRational, NumCoords);
  1382.     CagdSrfStruct *Srfs[CAGD_MAX_PT_SIZE],
  1383.     *Srf = CagdSrfNew(SrfX -> GType, PType, ULength, VLength);
  1384.  
  1385.     Srfs[0] = SrfW;
  1386.     Srfs[1] = SrfX;
  1387.     Srfs[2] = SrfY;
  1388.     Srfs[3] = SrfZ;
  1389.  
  1390.     Srf -> UOrder = SrfX -> UOrder;
  1391.     Srf -> VOrder = SrfX -> VOrder;
  1392.     if (SrfX -> UKnotVector != NULL)
  1393.     Srf -> UKnotVector = BspKnotCopy(SrfX -> UKnotVector,
  1394.                      ULength + SrfX -> UOrder);
  1395.     if (SrfX -> VKnotVector != NULL)
  1396.     Srf -> VKnotVector = BspKnotCopy(SrfX -> VKnotVector,
  1397.                      VLength + SrfX -> VOrder);
  1398.  
  1399.     for (i = !IsRational; i <= NumCoords; i++) {
  1400.     if (Srfs[i] != NULL) {
  1401.         if (Srfs[i] -> PType != CAGD_PT_E1_TYPE) {
  1402.         if (Srfs[i] -> PType != CAGD_PT_P1_TYPE)
  1403.             SYMB_FATAL_ERROR(SYMB_ERR_SCALAR_EXPECTED);
  1404.         else if (SrfW == NULL && WeightCopied == FALSE) {
  1405.             SYMB_GEN_COPY(Srf -> Points[0], Srfs[i] -> Points[0],
  1406.                   sizeof(CagdRType) * ULength * VLength);
  1407.             WeightCopied = TRUE;
  1408.         }
  1409.         }
  1410.  
  1411.         SYMB_GEN_COPY(Srf -> Points[i], Srfs[i] -> Points[1],
  1412.               sizeof(CagdRType) * ULength * VLength);
  1413.     }
  1414.     }
  1415.  
  1416.     return Srf;
  1417. }
  1418.  
  1419. /*****************************************************************************
  1420. * DESCRIPTION:                                                               M
  1421. * Promote a scalar curve to two dimensions by moving the scalar axis to be   M
  1422. * the Y axis and adding monotone X axis.                     M
  1423. *                                                                            *
  1424. * PARAMETERS:                                                                M
  1425. *   Crv:      Scalar curve to promose to a two dimensional one.              M
  1426. *   Min:      Minimum of new monotone X axis.                                M
  1427. *   Max:      Maximum of new monotone X axis.                                M
  1428. *                                                                            *
  1429. * RETURN VALUE:                                                              M
  1430. *   CagdCrvStruct *:  A two dimensional curve.                               M
  1431. *                                                                            *
  1432. * KEYWORDS:                                                                  M
  1433. *   SymbPrmtSclrCrvTo2D, promotion, conversion, symbolic computation         M
  1434. *****************************************************************************/
  1435. CagdCrvStruct *SymbPrmtSclrCrvTo2D(CagdCrvStruct *Crv,
  1436.                    CagdRType Min,
  1437.                    CagdRType Max)
  1438. {
  1439.     int i,
  1440.     Length = Crv -> Length;
  1441.     CagdBType
  1442.     IsRational = CAGD_IS_RATIONAL_CRV(Crv);
  1443.     CagdRType *R, *Points, *WPoints,
  1444.     Step = (Max - Min) / (Length - 1);
  1445.     CagdCrvStruct
  1446.     *PrmtCrv = CagdCoerceCrvTo(Crv, IsRational ? CAGD_PT_P2_TYPE
  1447.                            : CAGD_PT_E2_TYPE);
  1448.  
  1449.     R = PrmtCrv -> Points[1];
  1450.     PrmtCrv -> Points[1] = PrmtCrv -> Points[2];
  1451.     PrmtCrv -> Points[2] = R;
  1452.  
  1453.     Points = PrmtCrv -> Points[1];
  1454.     WPoints = IsRational ? PrmtCrv -> Points[0] : NULL;
  1455.     for (i = 0; i < Length; i++)
  1456.     *Points++ = (Min + Step * i) * (IsRational ? *WPoints++ : 1.0);
  1457.  
  1458.     return PrmtCrv;
  1459. }
  1460.  
  1461. /*****************************************************************************
  1462. * DESCRIPTION:                                                               M
  1463. * Promote a scalar surface to three dimensions by moving the scalar axis to  M
  1464. * be the Z axis and adding monotone X and Y axes.                 M
  1465. *                                                                            *
  1466. * PARAMETERS:                                                                M
  1467. *   Srf:                                                                     M
  1468. *   UMin:     Minimum of new monotone X axis.                                M
  1469. *   UMax:     Maximum of new monotone X axis.                                M
  1470. *   VMin:     Minimum of new monotone Y axis.                                M
  1471. *   VMax:     Maximum of new monotone X axis.                                M
  1472. *                                                                            *
  1473. * RETURN VALUE:                                                              M
  1474. *   CagdSrfStruct *:    A three dimensional surface.                         M
  1475. *                                                                            *
  1476. * KEYWORDS:                                                                  M
  1477. *   SymbPrmtSclrSrfTo3D, promotion, conversion, symbolic computation         M
  1478. *****************************************************************************/
  1479. CagdSrfStruct *SymbPrmtSclrSrfTo3D(CagdSrfStruct *Srf,
  1480.                    CagdRType UMin,
  1481.                    CagdRType UMax,
  1482.                    CagdRType VMin,
  1483.                    CagdRType VMax)
  1484. {
  1485.     int i, j,
  1486.     ULength = Srf -> ULength,
  1487.     VLength = Srf -> VLength;
  1488.     CagdBType
  1489.     IsRational = CAGD_IS_RATIONAL_SRF(Srf);
  1490.     CagdRType *R, *Points, *WPoints,
  1491.     UStep = (UMax - UMin) / (ULength - 1),
  1492.     VStep = (VMax - VMin) / (VLength - 1);
  1493.     CagdSrfStruct
  1494.     *PrmtSrf = CagdCoerceSrfTo(Srf, IsRational ? CAGD_PT_P3_TYPE
  1495.                            : CAGD_PT_E3_TYPE);
  1496.  
  1497.     R = PrmtSrf -> Points[1];
  1498.     PrmtSrf -> Points[1] = PrmtSrf -> Points[3];
  1499.     PrmtSrf -> Points[3] = R;
  1500.  
  1501.     Points = PrmtSrf -> Points[1];
  1502.     WPoints = IsRational ? PrmtSrf -> Points[0] : NULL;
  1503.     for (j = 0; j < VLength; j++)
  1504.     for (i = 0; i < ULength; i++)
  1505.         *Points++ = (UMin + UStep * i) *
  1506.         (IsRational ? *WPoints++ : 1.0);
  1507.  
  1508.     Points = PrmtSrf -> Points[2];
  1509.     WPoints = IsRational ? PrmtSrf -> Points[0] : NULL;
  1510.     for (j = 0; j < VLength; j++)
  1511.     for (i = 0; i < ULength; i++)
  1512.         *Points++ = (VMin + VStep * j) *
  1513.         (IsRational ? *WPoints++ : 1.0);
  1514.  
  1515.     return PrmtSrf;
  1516. }
  1517.  
  1518. /*****************************************************************************
  1519. * DESCRIPTION:                                                               M
  1520. * Given a controlpolygon/mesh, computes the extremum values of them all.     M
  1521. *                                                                            *
  1522. * PARAMETERS:                                                                M
  1523. *   Points:       To scan for extremum values.                     M
  1524. *   Length:       Length of each vector in Points.                           M
  1525. *   FindMinimum:  TRUE for minimum, FALSE for maximum.                       M
  1526. *                                                                            *
  1527. * RETURN VALUE:                                                              M
  1528. *   CagdRType *:  A vector holding PType point with the extremum values of   M
  1529. *                 each axis independently.                                   M
  1530. *                                                                            *
  1531. * KEYWORDS:                                                                  M
  1532. *   SymbExtremumCntPtVals, extremum values, symbolic computation             M
  1533. *****************************************************************************/
  1534. CagdRType *SymbExtremumCntPtVals(CagdRType **Points,
  1535.                  int Length,
  1536.                  CagdBType FindMinimum)
  1537. {
  1538.     static CagdRType Extremum[CAGD_MAX_PT_SIZE];
  1539.     int i, j;
  1540.  
  1541.     for (i = 1; Points[i] != NULL && i <= CAGD_MAX_PT_COORD; i++) {
  1542.     CagdRType
  1543.         *R = Points[0],
  1544.         *P = Points[i];
  1545.  
  1546.     Extremum[i] = FindMinimum ? INFINITY : -INFINITY;
  1547.  
  1548.     for (j = 0; j < Length; j++) {
  1549.         CagdRType
  1550.         Val = R == NULL ? *P++ : *P++ / *R++;
  1551.  
  1552.         if (FindMinimum) {
  1553.         if (Extremum[i] > Val)
  1554.             Extremum[i] = Val;
  1555.         }
  1556.         else {
  1557.         if (Extremum[i] < Val)
  1558.             Extremum[i] = Val;
  1559.         }
  1560.     }
  1561.     }
  1562.  
  1563.     return Extremum;
  1564. }
  1565.  
  1566.